package utils

import (
	"encoding/json"
	"errors"
	"gitcode.com/G-YT/iHealth25/server/config"
	requests "github.com/mozillazg/request"
	"net/http"
)

type (
	Audit interface {
		AuditText(text string) (bool, error)
		AuditImageUrl(imageUrl string) (bool, error)
	}
	audit struct {
		Token
		objs  []config.Obj
		index int
	}
	Token struct {
		AccessToken string `json:"access_token"`
	}
	ResponseTextAudit struct {
		ErrorCode      int    `json:"error_code"`
		ErrorMsg       string `json:"error_msg"`
		LogId          int64  `json:"log_id"`
		Conclusion     string `json:"conclusion"`
		ConclusionType int    `json:"conclusionType"`
	}
)

func CreateAudit(cfg []config.Obj) Audit {
	return &audit{
		objs: cfg,
	}
}

func (a *audit) getToken(obj config.Obj) error {
	url := "https://aip.baidubce.com/oauth/2.0/token"
	client := new(http.Client)
	req := requests.NewRequest(client)
	req.Params = map[string]string{
		"client_id":     obj.ApiKEY,
		"client_secret": obj.SecretKey,
		"grant_type":    "client_credentials",
	}
	if response, err := req.Get(url); err != nil {
		return err
	} else {
		defer response.Body.Close()
		data, _ := response.Content()
		json.Unmarshal(data, &a.Token)
	}
	return nil
}

func (a *audit) AuditText(text string) (bool, error) {
	var (
		res *ResponseTextAudit
		err error
	)
	if res, err = a.auditText(text); err != nil {
		return false, err
	} else if res.ErrorCode == 110 {
		a.index = (a.index + 1) % len(a.objs)
		a.getToken(a.objs[a.index])
		res, err = a.auditText(text)
		if err != nil {
			return false, err
		}
	}
	if res.ErrorCode != 0 {
		return false, errors.New(res.ErrorMsg)
	}
	return res.ConclusionType != 2, nil
}

func (a *audit) AuditImageUrl(imageUrl string) (bool, error) {
	var (
		res *ResponseTextAudit
		err error
	)
	if res, err = a.auditImageUrl(imageUrl); err != nil {
		return false, err
	} else if res.ErrorCode == 110 {
		a.index = (a.index + 1) % len(a.objs)
		a.getToken(a.objs[a.index])
		res, err = a.auditImageUrl(imageUrl)
		if err != nil {
			return false, err
		}
	}
	if res.ErrorCode != 0 {
		return false, errors.New(res.ErrorMsg)
	}
	return res.ConclusionType != 2, nil
}

func (a *audit) auditText(text string) (*ResponseTextAudit, error) {
	if len(a.Token.AccessToken) == 0 {
		a.index = (a.index + 1) % len(a.objs)
		a.getToken(a.objs[a.index])
	}
	url := "https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined"
	client := new(http.Client)
	req := requests.NewRequest(client)
	req.Headers = map[string]string{
		"Content-Type": "application/x-www-form-urlencoded",
	}
	req.Params = map[string]string{
		"access_token": a.AccessToken,
	}
	req.Data = map[string]string{"text": text}
	if response, err := req.Post(url); err != nil {
		return nil, err
	} else {
		defer response.Body.Close()
		data, _ := response.Content()
		var res ResponseTextAudit
		return &res, json.Unmarshal(data, &res)
	}
}

func (a *audit) auditImageUrl(imageUrl string) (*ResponseTextAudit, error) {
	if len(a.Token.AccessToken) == 0 {
		a.index = (a.index + 1) % len(a.objs)
		a.getToken(a.objs[a.index])
	}
	url := "https://aip.baidubce.com/rest/2.0/solution/v1/img_censor/v2/user_defined"
	client := new(http.Client)
	req := requests.NewRequest(client)
	req.Headers = map[string]string{
		"Content-Type": "application/x-www-form-urlencoded",
	}
	req.Params = map[string]string{
		"access_token": a.AccessToken,
	}
	req.Data = map[string]string{"imgUrl": imageUrl}
	if response, err := req.Post(url); err != nil {
		return nil, err
	} else {
		defer response.Body.Close()
		data, _ := response.Content()
		var res ResponseTextAudit
		return &res, json.Unmarshal(data, &res)
	}
}
